package com.aqgj.util;


import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import org.springframework.util.Assert;

import javax.persistence.Query;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by Jetvae on 2017/6/22.
 */
public class BaseDaoImpl<T extends BaseEntity> extends HibernateDaoSupport implements IBaseDao<T> {
    protected Class<T> entityClass;

    public BaseDaoImpl() {
        this.entityClass = GenericsUtils.getSuperClassGenricType(getClass());
    }

    @Autowired
    public void setSessionFactoryo(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }

    public T get(Serializable id) {
        return getHibernateTemplate().get(this.entityClass, id);
    }

    public Object get(Class objClass, Serializable id) {
        return getHibernateTemplate().get(objClass, id);
    }

    public List<T> getAll() {
        return getHibernateTemplate().loadAll(this.entityClass);
    }

    public List<T> getAll(String orderBy, boolean isAsc) {
        Assert.hasText(orderBy);
        if (isAsc) {
            return (List<T>) getHibernateTemplate().findByCriteria(
                    DetachedCriteria.forClass(this.entityClass).addOrder(Order.asc(orderBy)));
        }
        return (List<T>) getHibernateTemplate().findByCriteria(
                DetachedCriteria.forClass(this.entityClass).addOrder(Order.desc(orderBy)));
    }

    public List<T> findBy(String propertyName, Object value) {
        Assert.hasText(propertyName);
        String hql="from "+this.entityClass.getName()+" z where z."+propertyName+"='"+value+"'";
        return (List<T>) getHibernateTemplate().getSessionFactory().getCurrentSession().createQuery(hql).list();
    }


    public T findUniqueBy(String propertyName, Object value) {
        Assert.hasText(propertyName);
        String hql="from "+this.entityClass.getName()+" z where z."+propertyName+"='"+value+"'";
        return (T) getHibernateTemplate().getSessionFactory().getCurrentSession().createQuery(hql).uniqueResult();
    }

    public List<T> findBy(String propertyName1, Object value1,String propertyName2, Object value2 ) {
        Assert.hasText(propertyName1);
        Assert.hasText(propertyName2);
        String hql="from "+this.entityClass.getName()+" z where z."+propertyName1+"='"+value1+"' and z."+propertyName2+"='"+value2+"'";
        return (List<T>) getHibernateTemplate().getSessionFactory().getCurrentSession().createQuery(hql).list();
    }
    public List<T> findLike(String propertyName1, Object value1,String propertyName2, Object value2 ) {
        Assert.hasText(propertyName1);
        Assert.hasText(propertyName2);
        String hql="from "+this.entityClass.getName()+" z where z."+propertyName1+"like'%"+value1+"%' and z."+propertyName2+"like'%"+value2+"%'";
        return (List<T>) getHibernateTemplate().getSessionFactory().getCurrentSession().createQuery(hql).list();
    }
    public List<T> findLike(int pageNo, int pageSize,String propertyName1, Object value1,String propertyName2, Object value2 ) {
        Assert.hasText(propertyName1);
        Assert.hasText(propertyName2);
        String hql="from "+this.entityClass.getName()+" z where z."+propertyName1+"like'%"+value1+"%' and z."+propertyName2+"like'%"+value2+"%'";
        Query query = getSessionFactory().getCurrentSession().createQuery(hql);
        query.setFirstResult(pageNo*pageSize);//设置起始行
        query.setMaxResults(pageSize);
        return query.getResultList();
    }
    public void remove(BaseEntity object) {
        getHibernateTemplate().delete(object);
    }

    public void removeById(Serializable id) {
        String className = this.entityClass.getName();
        createQuery("delete " + className + " where id=?", new Object[]{id}).executeUpdate();
    }

    public void removeById(Class objClass, Serializable id) {
        getHibernateTemplate().delete(get(objClass, id));
    }


    public void save(BaseEntity object) {
        if (object.getId() == null || object.getId().isEmpty()) {
            object.setId(null);
        }
        getHibernateTemplate().saveOrUpdate(object);
    }

    public List<T> listQuery(String hql, Object... values) {
        Query query = createQuery(hql, values);
        List list = query.getResultList();
        return list;
    }


    public Query createSQLQuery(String sql, Object... values) {
        Assert.hasText(sql);
        Query query = getSessionFactory().getCurrentSession().createNativeQuery(sql);
        for (int i = 0; i < values.length; i++) {
            query.setParameter(i, values[i]);
        }
        return query;
    }

    public Query createQuery(String hql, Object... values) {
        Assert.hasText(hql);
        Query query = getSessionFactory().getCurrentSession().createQuery(hql);
        for (int i = 0; i < values.length; i++) {
            query.setParameter(i, values[i]);
        }
        return query;
    }

    private static String removeSelect(String hql) {
        Assert.hasText(hql);
        int beginPos = hql.toLowerCase().indexOf("from");
        Assert.isTrue(beginPos != -1, " hql : " + hql + " must has a keyword 'from'");
        return hql.substring(beginPos);
    }

    private static String removeOrders(String hql) {
        Assert.hasText(hql);
        Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", 2);
        Matcher m = p.matcher(hql);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(sb, "");
        }
        m.appendTail(sb);
        return sb.toString();
    }
    /**
     * 分页查询
     * @param paramBaseEntity 实体bean
     * @param pageNo 页面数（第几页）
     * @param pageSize 当前页面显示总条数
     * @return
     */
    public List<T> listPagQuery(BaseEntity paramBaseEntity, int pageNo, int pageSize) {
        String className = paramBaseEntity.getClass().getName();
        String hql=" from "+className;
        Query query = getSessionFactory().getCurrentSession().createQuery(hql);
        query.setFirstResult(pageNo*pageSize);//设置起始行
        query.setMaxResults(pageSize);//每页条数
        //Query.setMaxResults方法简单地设置需要查询的最大结果集。
        //query.setFirstResult(0),query.setMaxResults(4);相当于MySQL中的limit 0, 4;

        List cats = query.getResultList();
        return cats;
    }
    /**
     * 分页查询,查询当前dao对应实体bean的分页。
     * @param pageNo 页面数（第几页）
     * @param pageSize 当前页面显示总条数
     * @return
     */
    public List<T> listPagQuery(int pageNo, int pageSize) {
        String className = this.entityClass.getName();
        String hql=" from "+className;
        Query query = getSessionFactory().getCurrentSession().createQuery(hql);
        query.setFirstResult(pageNo*pageSize);//设置起始行
        query.setMaxResults(pageSize);//每页条数
        //Query.setMaxResults方法简单地设置需要查询的最大结果集。
        //query.setFirstResult(0),query.setMaxResults(4);相当于MySQL中的limit 0, 4;

        List cats = query.getResultList();
        return cats;
    }
    /**
     * 分页查询,通过sql查询。
     * @param pageNo 页面数（第几页）从1开始
     * @param pageSize 当前页面显示总条数
     * @return
     */
    public List<T> listPagQuery(String hql,int pageNo, int pageSize,Object... values) {
        if(pageNo<=1){pageNo=0;}else{pageNo=pageNo-1;}
        if(pageSize<=0){pageSize=10;}
        Query query = getSessionFactory().getCurrentSession().createQuery(hql);
        for (int i = 0; i < values.length; i++) {
            query.setParameter(i, values[i]);
        }
        query.setFirstResult(pageNo*pageSize);//设置起始行
        query.setMaxResults(pageSize);//每页条数
        //Query.setMaxResults方法简单地设置需要查询的最大结果集。
        //query.setFirstResult(0),query.setMaxResults(4);相当于MySQL中的limit 0, 4;
        List cats = query.getResultList();
        return cats;
    }
    /**
     * 分页查询,通过sql查询。
     * @param pageNo 页面数（第几页）从1开始
     * @param pageSize 当前页面显示总条数
     * @return
     */
    public List<T> listSqlPagQuery(String sql,int pageNo, int pageSize) {
        if(pageNo<=1){pageNo=0;}else{pageNo=pageNo-1;}
        if(pageSize<=0){pageSize=10;}
        Query query = getSessionFactory().getCurrentSession().createNativeQuery(sql);
        query.setFirstResult(pageNo*pageSize);//设置起始行
        query.setMaxResults(pageSize);//每页条数
        //Query.setMaxResults方法简单地设置需要查询的最大结果集。
        //query.setFirstResult(0),query.setMaxResults(4);相当于MySQL中的limit 0, 4;
        List cats = query.getResultList();
        return cats;
    }
    /**
     * 分页查询,通过sql查询。 可调用实现装bean；
     * @param pageNo 页面数（第几页）从1开始
     * @param pageSize 当前页面显示总条数
     * @return query
     */
    public Query SqlPagQuery(String sql,int pageNo, int pageSize) {
        if(pageNo<=1){pageNo=0;}else{pageNo=pageNo-1;}
        if(pageSize<=0){pageSize=10;}
        Query query = getSessionFactory().getCurrentSession().createNativeQuery(sql);
        query.setFirstResult(pageNo*pageSize);//设置起始行
        query.setMaxResults(pageSize);//每页条数
        return query;
    }
    /**
     * 分页查询,通过sql查询。 可调用实现装bean；
     * @return int
     */
    public Integer getSqlSumQuery(String sql) {
        String sumSql="select COUNT(*)  from ( "+sql+" ) otherName";
        Query query = getSessionFactory().getCurrentSession().createNativeQuery(sumSql);
        List list=query.getResultList();
        String sumString=list.get(0).toString();
        return  Integer.parseInt(sumString) ;

    }
    /**
     * 分页查询,通过sql查询。返回数组和总数
     * @param pageNo 页面数（第几页）从1开始
     * @param pageSize 当前页面显示总条数
     * @return List<T> lists{Sum:int；List<T>list  </>}
     * sql语句不能命名重复，例如连表查询时，不能出现两个id。请取别名
     */
    public HashMap<String,Object> listAndSumSqlPagQuery(String sql, int pageNo, int pageSize) {
        HashMap<String,Object> map=new HashMap<>();
        String sumSql="select COUNT(*)  from ( "+sql+" ) otherName";
        String  sum = getSessionFactory().getCurrentSession().createNativeQuery(sumSql).getResultList().get(0).toString();
        if(pageNo<=1){pageNo=0;}else{pageNo=pageNo-1;}
        if(pageSize<=0){pageSize=10;}
        Query query = getSessionFactory().getCurrentSession().createNativeQuery(sql);
        query.setFirstResult(pageNo*pageSize);//设置起始行
        query.setMaxResults(pageSize);//每页条数
        List cats = query.getResultList();
        map.put("sum",Integer.parseInt(sum));
        map.put("data",cats);
        return map;
    }
    /**
     * 将list 对应key，返回键值对应完整的list；
     * @param list sql查询出的集合
     * @param stringArray list对应的key值。
     * @return
     */
    public List getKeyList(List list,String ...stringArray){
        List newList= new ArrayList();
        for (int n=0;n<list.size();n++){
            Object[] bean=(Object[])list.get(n);
            Map map =new HashMap();
            for (int i=0;i<stringArray.length;i++){
                map.put(stringArray[i],bean[i]);
            }
            newList.add(map);
        }
        return newList;
    }

}